home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / amiga.free / sorgenti vari / wolf3dmacsource.sit / Wolf3DMacSource / Refresh.c < prev    next >
C/C++ Source or Header  |  1994-10-06  |  11KB  |  480 lines

  1. #include "WolfDef.h"
  2. #include <string.h>
  3. #include <math.h>
  4.  
  5. #define    DOORPIC    59
  6.  
  7. /* Scale ranges from 0xffff (one tile == 512 pixels high) down to 0x100 (one tile == 2 pixels) */
  8.  
  9. savenode_t *nodes;
  10. saveseg_t *pwallseg;                /* pushwall in motion*/
  11.  
  12. /*
  13. ================================================
  14.  
  15.                 MATH ROUTINES
  16.  
  17. ================================================
  18. */
  19.  
  20. /* -8.8 * -0.8 = -8.8*/
  21. fixed_t    FixedByFrac (fixed_t a, fixed_t b)
  22. {
  23.     fixed_t    c;
  24.     c = ((long)a * (long)b)>>FRACBITS;
  25.     return c;
  26. }
  27.  
  28. /* -8.8 * -0.8 = -8.8*/
  29. fixed_t    SUFixedMul (fixed_t a, ufixed_t b)
  30. {
  31.     fixed_t    c;
  32.     c = ((long)a * (long)b)>>FRACBITS;
  33.     return c;
  34. }
  35.  
  36. /* -8.8 / -8.8 = -8.8*/
  37. fixed_t    FixedDiv (fixed_t a, fixed_t b)
  38. {
  39.     a = (long)(((long)a<<FRACBITS) / (long)b);
  40.     return a;
  41. }
  42.  
  43. /**********************************
  44.  
  45.     Return the x coord for a sprite
  46.     
  47. **********************************/
  48.  
  49. fixed_t R_TransformX(fixed_t x,fixed_t y)
  50. {
  51.     fixed_t gxt,gyt;
  52.     gxt = FixedByFrac(x,viewsin);
  53.     gyt = FixedByFrac(y,viewcos);
  54.     return gxt-gyt;
  55. }
  56.  
  57. /**********************************
  58.  
  59.     Return the scale factor for a sprite
  60.     
  61. **********************************/
  62.  
  63. fixed_t R_TransformZ(fixed_t x,fixed_t y)
  64. {
  65.     fixed_t    gxt,gyt;
  66.     gxt = FixedByFrac(x,viewcos);
  67.     gyt = FixedByFrac(y,viewsin);
  68.     return gxt+gyt;
  69. }
  70.  
  71. /**********************************
  72.  
  73.     Return the scale factor from a 64k range angle
  74.     
  75. **********************************/
  76.  
  77. Word ScaleFromGlobalAngle(int visangle,int distance)
  78. {
  79.     fixed_t    tz;
  80.  
  81.     Word anglea, angleb;
  82.     Word sinea, sineb;
  83.     
  84.     visangle >>= ANGLETOFINESHIFT;
  85.     anglea = (FINEANGLES/4 + (visangle-centerangle))&(FINEANGLES/2-1);
  86.     angleb = (FINEANGLES/4 + (visangle-normalangle))&(FINEANGLES/2-1);
  87.     sinea = finesine[anglea];    /* bothe sines are always positive*/
  88.     sineb = finesine[angleb];
  89.     
  90.     tz = ((long)distance * sinea) / sineb;
  91.  
  92.     if (tz>=MAXZ) {        /* Make sure it's not too big... */
  93.         tz = MAXZ-1;
  94.     }
  95.     return scaleatzptr[tz];        /* Return the size */
  96. }
  97.  
  98. /**********************************
  99.  
  100.     The automap has to be done in quadrants for various reasons
  101.     
  102. **********************************/
  103.  
  104. void DrawAutomap(Word tx,Word ty)
  105. {
  106.     Word i, tile;
  107.     saveseg_t *seg;
  108.     Word x,y,xstep,ystep,count;
  109.     Word min,max;
  110.     Word maxtx, maxty;
  111.     Word NodeCount;
  112.     
  113.     NodeCount = MapPtr->numnodes;
  114.     maxtx = tx+(SCREENWIDTH/16);
  115.     maxty = ty+(SCREENHEIGHT/16);
  116.     seg = (saveseg_t *)nodes;
  117.     i = 0;
  118.     do {
  119.         if ( (seg->dir & (DIR_SEGFLAG|DIR_SEENFLAG)) == (DIR_SEGFLAG|DIR_SEENFLAG) ) {
  120.             min = (seg->min-1)>>1;
  121.             max = (seg->max+3)>>1;
  122.         
  123.             switch (seg->dir&3) {
  124.             case di_north:
  125.                 x = (seg->plane-1)>>1;
  126.                 y = min;
  127.                 xstep = 0;
  128.                 ystep = 1;
  129.                 break;
  130.             case di_south:
  131.                 x = seg->plane>>1;
  132.                 y = min;
  133.                 xstep = 0;
  134.                 ystep = 1;
  135.                 break;
  136.             case di_east:
  137.                 y = (seg->plane-1)>>1;
  138.                 x = min;
  139.                 xstep = 1;
  140.                 ystep = 0;
  141.                 break;
  142.             case di_west:
  143.                 y = seg->plane>>1;
  144.                 x = min;
  145.                 xstep = 1;
  146.                 ystep = 0;
  147.                 break;
  148.             }
  149.         
  150.             for (count=max-min ; count ; --count,x+=xstep,y+=ystep) {
  151.                 if (x < tx || x >= maxtx || y < ty || y>=maxty) {
  152.                     continue;
  153.                 }
  154.                 tile = tilemap[y][x];
  155.                 if (tile & TI_DOOR) {
  156.                     tile = 59 /*(seg->dir&1) + 30*/;
  157.                 } else if (tile & TI_PUSHWALL) {
  158.                     if (ShowPush) {
  159.                         tile = 64;
  160.                     } else {
  161.                         tile = textures[y][x];
  162.                     }
  163.                 } else {
  164.                     tile = MapPtr->tilemap[y][x];
  165.                     if (! (tile&0x80) ) {
  166.                         continue;        /* not a solid tile*/
  167.                     }
  168.                     tile = textures[y][x]; 
  169.                 }
  170.                 DrawSmall(x-tx,y-ty,tile);    /* Draw the tile on the screen */
  171.             }    
  172.         }
  173.         ++seg;    
  174.     } while (++i<NodeCount);
  175.     x = viewx>>8;
  176.     y = viewy>>8;
  177.     if (x >= tx && x < maxtx && y >= ty && y<maxty) {
  178.         DrawSmall(x-tx,y-ty,64);        /* Draw BJ's face here */
  179.     }
  180.     BlastScreen();
  181. }
  182.  
  183. /**********************************
  184.  
  185.     Init my math tables for the current view
  186.     
  187. **********************************/
  188.  
  189. #define    PI    3.141592657
  190.  
  191. Boolean StartupRendering(Word NewSize)
  192. {
  193. #ifdef __MAC__
  194.     int        i;
  195.     Word minz;
  196.     int        x;
  197.     float    a, fv;
  198.     long    t;
  199.     LongWord focallength;
  200.     Word j;
  201.     Word *ScalePtr;
  202. #endif
  203.  
  204.     if (NewSize == MathSize) {    /* Already loaded? */
  205.         return TRUE;
  206.     }
  207.     
  208. #ifdef __MAC__        /* Only the mac version will calculate the tables */
  209.  
  210. /* generate scaleatz*/
  211.  
  212.     ScalePtr = scaleatzptr;
  213.     minz = PROJECTIONSCALE/MAXFRAC;        /* What's the largest index */        
  214.     for (j=0;j<=minz;j++) {                
  215.         ScalePtr[j] = MAXFRAC;        /* Fill in the overflow area (No longs) */
  216.     }
  217.     do {                    /* Calculate the rest */
  218.         ScalePtr[j] = PROJECTIONSCALE/j;    /* Create whole numbers */
  219.     } while (++j<MAXZ);
  220.  
  221. /* viewangle tangent table*/
  222.  
  223.     if (MathSize==-1) {        /* Only needs to be done once */
  224.         i = 0;
  225.         do {
  226.             a = (i-FINEANGLES/4+0.1)*PI*2/FINEANGLES;
  227.             fv = 256*tan(a);
  228.             if (fv>0x7fff) {
  229.                 t = 0x7fff;
  230.             } else if (fv<-0x7fff) {
  231.                 t = -0x7fff;
  232.             } else {
  233.                 t = fv;
  234.             }
  235.             finetangent[i] = t;
  236.         } while (++i<FINEANGLES/2);
  237.     
  238. /* finesine table*/
  239.         
  240.         i = 0;
  241.         do {
  242.             a = (i+0.0)*PI*2/FINEANGLES;
  243.             t = 256*sin(a);
  244.             if (t>255) {
  245.                 t = 255;
  246.             }
  247.             if (t<1) {
  248.                 t = 1;
  249.             }
  250.             finesine[i] = t;
  251.         } while (++i<FINEANGLES/2);
  252.     }
  253.  
  254. /* use tangent table to generate viewangletox*/
  255.  
  256.     /* calc focallength so FIELDOFVIEW angles covers SCREENWIDTH */
  257.  
  258.     focallength = (SCREENWIDTH/2)<<FRACBITS/finetangent[FINEANGLES/4+FIELDOFVIEW/2];
  259.     i = 0;
  260.     do {
  261.         t = ((long) finetangent[i]*(long)focallength)>>FRACBITS;
  262.         t = (int)SCREENWIDTH/2 - t;
  263.         if (t < -1) {
  264.             t = -1;
  265.         } else if (t>(int)SCREENWIDTH+1) {
  266.             t = SCREENWIDTH+1;
  267.         }
  268.         viewangletox[i] = t;
  269.     } while (++i<FINEANGLES/2);
  270.  
  271. /* scan viewangletox[] to generate xtoviewangle[]*/
  272.  
  273.     x = 0;
  274.     do {
  275.         i = 0;
  276.         while (viewangletox[i]>=x) {
  277.             i++;
  278.         }
  279.         xtoviewangle[x] = i-FINEANGLES/4-1;
  280.     } while (++x<=SCREENWIDTH);
  281.  
  282. /* take out the fencepost cases from viewangletox*/
  283.  
  284.     for (i=0 ; i<FINEANGLES/2 ; i++) {
  285.         t = SUFixedMul (finetangent[i], focallength);
  286.         t = (int)SCREENWIDTH/2 - t;
  287.         if (viewangletox[i] == -1) {
  288.             viewangletox[i] = 0;
  289.         } else if (viewangletox[i] == SCREENWIDTH+1) {
  290.             viewangletox[i] = SCREENWIDTH;
  291.         }
  292.     }
  293.     
  294. #if 0        /* Should I save these tables? */
  295. if (!NewSize) {
  296. SaveJunk(scaleatzptr,sizeof(Word)*MAXZ);
  297. SaveJunk(finetangent,sizeof(short)*FINEANGLES/2);
  298. SaveJunk(finesine,sizeof(short)*FINEANGLES/2);
  299. SaveJunk(viewangletox,sizeof(short)*FINEANGLES/2);
  300. SaveJunk(xtoviewangle,sizeof(short)*(SCREENWIDTH+1));
  301. GoodBye();
  302. }
  303. #endif
  304.     
  305. #else
  306. /* All other versions load the tables from disk (MUCH FASTER!!) */
  307.     if (MathSize==-1) {
  308.         finetangent = LoadAResource(rFineTangent);
  309.         finesine = LoadAResource(rFineSine);
  310.     }
  311.     scaleatzptr = LoadAResource(rScaleAtZ);
  312.     viewangletox = LoadAResource(rViewAngleToX);
  313.     xtoviewangle = LoadAResource(rXToViewAngle);
  314. #endif
  315.  
  316.     clipshortangle = xtoviewangle[0]<<ANGLETOFINESHIFT;    /* Save leftmost angle for view */
  317.     clipshortangle2 = clipshortangle*2;                    /* Double the angle for constant */
  318.     
  319. /* textures for doors stay the same across maps*/
  320.  
  321.     memset(textures[128],DOORPIC+4,MAPSIZE); /* door side*/
  322.     memset(textures[129],DOORPIC+0,MAPSIZE); /* regular door*/
  323.     memset(textures[130],DOORPIC+1,MAPSIZE); /* lock 1*/
  324.     memset(textures[131],DOORPIC+2,MAPSIZE); /* lock 2*/
  325.     memset(textures[132],DOORPIC+3,MAPSIZE); /* elevator*/
  326.     ReleaseScalers();        /* Release any compiled scalers */
  327.     if (!SetupScalers()) {                /* Redo any scalers */
  328.         return FALSE;
  329.     }
  330.     MathSize = NewSize;
  331.     return TRUE;
  332. }
  333.  
  334. /**********************************
  335.  
  336.     Alert the rendering engine about a new map
  337.     
  338. **********************************/
  339.  
  340. void NewMap(void)
  341. {
  342.     Word x,y, tile;
  343.     Byte *src;
  344. #ifdef __BIGENDIAN__
  345.     savenode_t *FixPtr;
  346. #endif
  347.     memset(textures,0xff,128*64);    /* clear array so pushwall spawning can insert*/
  348.                                     /* texture numbers in empty spots*/
  349.     src = &MapPtr->tilemap[0][0];
  350.     y = 0;
  351.     do {
  352.         x = 0;
  353.         do {
  354.             tile = *src++;
  355.             if (tile&TI_BLOCKMOVE) {    /* blocking?*/
  356.                 tile = ((tile&0x3f)-1)*2;
  357.                 textures[MAPSIZE+x][y] = tile + 1;    /* Use the dark shape */
  358.                 textures[y][x] = tile;            /* Use the light shape */
  359.             }
  360.         } while (++x<MAPSIZE);
  361.     } while (++y<MAPSIZE);
  362.     
  363.     nodes = (savenode_t *)((Byte *)MapPtr + MapPtr->nodelistofs);
  364. #ifdef __BIGENDIAN__
  365.     y = MapPtr->numnodes;
  366.     FixPtr = nodes;
  367.     while (y) {
  368.         FixPtr->children[0] = SwapUShort(FixPtr->children[0]);    /* Swap endian on all offsets */
  369.         FixPtr->children[1] = SwapUShort(FixPtr->children[1]);
  370.         ++FixPtr;
  371.         --y;
  372.     }    
  373. #endif
  374.     pwallseg = 0;        /* No pushwalls in progress */
  375.     
  376. }
  377.  
  378. /**********************************
  379.  
  380.     Set up my pushwall record so the BSP records will follow
  381.     
  382. **********************************/
  383.  
  384. void StartPushWall(void)
  385. {
  386.     Word i;
  387.     Word segdir,segplane,segmin;
  388.     saveseg_t *SavePtr;                /* Temp pointer */
  389.  
  390.     pwallseg = 0;    /* No pushwalls in progress */
  391.             
  392.     switch (PushWallRec.pwalldir) {    /* Which direction? */
  393.     case CD_NORTH:
  394.         segmin = PushWallRec.pwallx<<1;    /* Minimum segment */
  395.         segplane = (PushWallRec.pwally+1)<<1;    /* y facing plane */
  396.         segdir = di_east;    /* Point east */
  397.         break;
  398.     case CD_EAST:
  399.         segplane = PushWallRec.pwallx<<1;    /* Minimum segment */
  400.         segmin = PushWallRec.pwally<<1;
  401.         segdir = di_south;    /* Point south */
  402.         break;
  403.     case CD_SOUTH:
  404.         segmin = PushWallRec.pwallx<<1;
  405.         segplane = PushWallRec.pwally<<1;
  406.         segdir = di_west;    /* Point west */
  407.         break;
  408.     case CD_WEST:
  409.         segplane = (PushWallRec.pwallx+1)<<1;
  410.         segmin = PushWallRec.pwally<<1;
  411.         segdir = di_north;    /* Point north */
  412.     }
  413.     
  414.     SavePtr = (saveseg_t *)nodes;    /* Init pointer to the nodes */
  415.     i = MapPtr->numnodes;        /* Get the node count */
  416.     if (i) {                /* Maps MUST have nodes */
  417.         do {
  418.             if ((SavePtr->dir & DIR_SEGFLAG) &&        /* Segmented? */
  419.                 ((SavePtr->dir & 3) == segdir) &&    /* Proper side? */
  420.                 (SavePtr->plane == segplane) &&        /* Proper plane? */
  421.                 (SavePtr->min == segmin) ) {        /* Proper segment */
  422.                     pwallseg = SavePtr;                /* Save the segment */
  423.                     return;                            /* Exit */
  424.             }
  425.             ++SavePtr;            /* Next index */
  426.         } while (--i);            /* Count down */
  427.     }
  428. }
  429.  
  430. /**********************************
  431.  
  432.     Mark a pushwall BSP segment as disabled
  433.     
  434. **********************************/
  435.  
  436. void AdvancePushWall(void)
  437. {
  438.     if (pwallseg) {        /* Failsafe */
  439.         pwallseg->dir |= DIR_DISABLEDFLAG;        /* Mark the pushwall as disabled */
  440.     }
  441. }
  442.  
  443. /**********************************
  444.  
  445.     Render the entire 3-D view
  446.     
  447. **********************************/
  448.  
  449. void RenderView(void)
  450. {
  451.  
  452.     Word frame;
  453.     
  454.     centerangle = gamestate.viewangle<<GAMEANGLETOFINE;    /* 512 to 2048 */
  455.     centershort = centerangle<<ANGLETOFINESHIFT;    /* 2048 to 64k */
  456.     viewsin = sintable[gamestate.viewangle];    /* Get the basic sine */
  457.     viewcos = costable[gamestate.viewangle];    /* Get the basic cosine */
  458.     memset(areavis, 0, sizeof(areavis));    /* No areas are visible */
  459.     ClearClipSegs();            /* Clip first seg only to sides of screen */    
  460.     IO_ClearViewBuffer();        /* Erase to ceiling / floor colors*/
  461.     
  462.     bspcoord[BSPTOP] = 0;        /* The map is 64*64 */
  463.     bspcoord[BSPBOTTOM] = 64*FRACUNIT;
  464.     bspcoord[BSPLEFT] = 0;
  465.     bspcoord[BSPRIGHT] = 64*FRACUNIT;
  466.     
  467.     RenderBSPNode(0);        /* traverse the BSP tree from the root */
  468.     DrawSprites();            /* sort all the sprites in any of the rendered areas*/
  469.     DrawTopSprite();        /* draw game over sprite on top of everything*/
  470.     
  471.     if (!NoWeaponDraw) {    /* Don't draw the weapon? */
  472.         frame = gamestate.attackframe;
  473.         if (frame == 4) {
  474.             frame = 1;            /* drop back frame*/
  475.         }
  476.         IO_AttackShape(gamestate.weapon*4 + frame);        /* Draw the gun shape */
  477.     }
  478.     IO_DisplayViewBuffer();    /* blit to screen */
  479. }
  480.